<?php
/**
 * 微信开放平台操作类
 * Class Weixin
 */
class WxOpenApi
{
    /**
     * 获取requestCode的api接口
     * @var string
     */
    protected $GetRequestCodeURL = 'https://open.weixin.qq.com/connect/qrconnect';
    
    /**
     * 获取access_token的api接口
     * @var string
     */
    protected $GetAccessTokenURL = 'https://api.weixin.qq.com/sns/oauth2/access_token';

    /**
     * API根路径
     * @var string
     */
    protected $ApiBase = 'https://api.weixin.qq.com/';

    /**
     * 应用唯一标识
     * @var string
     */
    private $_AppKey = '';

    /**
     * 应用密钥
     * @var string
     */
    private $_AppSecret = '';

    /**
     * 回调页面URL
     * @var string
     */
    private $_Callback = '';

    /**
     * 授权后获取到的TOKEN信息
     * @var array
     */
    protected $Token = null;

    /**
     * 构造函数
     */
    public function __construct($appkey='',$appsecret='',$callback=''){
        if($appkey)$this->_AppKey = $appkey;
        if($appsecret)$this->_AppSecret = $appsecret;
        if($callback)$this->_Callback = $callback;
    }

    /**
     * 请求code
     * @return string
     */
    public function getRequestCodeURL(){
        $params = array(
            'appid' => $this->_AppKey,
            'redirect_uri'=>$this->_Callback,
            'response_type'=>'code',
            'scope'=>'snsapi_login'
        );
        return $this->GetRequestCodeURL . '?' . http_build_query($params);
    }

    /**
     * 获取access_token
     * @param $code 上一步请求到的code
     * @param null $extend
     * @return mixed
     */
    public function getAccessToken($code, $extend = null){
        $params = array(
            'appid'     => $this->_AppKey,
            'secret'    => $this->_AppSecret,
            'grant_type'    => 'authorization_code',
            'code'          => $code,
        );
        return $this->http($this->GetAccessTokenURL, $params, 'POST');
    }

    /**
     * 组装接口调用参数 并调用接口
     * @param $api 微信API
     * @param string $param 调用API的额外参数
     * @param string $method HTTP请求方法 默认为GET
     * @param bool|false $multi
     * @return mixed
     */
    public function call($api, $param = '', $method = 'GET', $multi = false){
        /* 腾讯微博调用公共参数 */
        $params = array(
            'access_token'       => $this->Token['access_token'],
            'openid'             => $this->openid(),
        );
        $vars = $this->param($params, $param);
        $data = $this->http($this->url($api), $vars, $method, array(), $multi);
        return json_decode($data, true);
    }

    /**
     * 获取指定API请求的URL
     * @param  string $api API名称
     * @param  string $fix api后缀
     * @return string      请求的完整URL
     */
    protected function url($api, $fix = ''){
        return $this->ApiBase . $api . $fix;
    }

    
    /**
     * 获取当前授权应用的openid
     * @return mixed
     */
    public function openid(){
        $data = $this->Token;
        if(!empty($data['openid']))
            return $data['openid'];
        else
            exit('没有获取到微信用户ID！');
    }

    /**
     * 发送HTTP请求方法，目前只支持CURL发送请求
     * @param $url 请求URL
     * @param $params 请求参数 请求方法GET/POST
     * @param string $method 响应数据
     * @param array $header
     * @param bool|false $multi
     * @return mixed
     * @throws Exception
     */
    protected function http($url, $params, $method = 'GET', $header = array(), $multi = false){
        $opts = array(
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER     => $header
        );

        /* 根据请求类型设置特定参数 */
        switch(strtoupper($method)){
            case 'GET':
                $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
                break;
            case 'POST':
                //判断是否传输文件
                $params = $multi ? $params : http_build_query($params);
                $opts[CURLOPT_URL] = $url;
                $opts[CURLOPT_POST] = 1;
                $opts[CURLOPT_POSTFIELDS] = $params;
                break;
            default:
                throw new Exception('不支持的请求方式！');
        }

        /* 初始化并执行curl请求 */
        $ch = curl_init();
        curl_setopt_array($ch, $opts);
        $data  = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);
        if($error) throw new Exception('请求发生错误：' . $error);
        return  $data;
    }
}